package cn.ac.iscas.domain.job;


import cn.ac.iscas.domain.component.reader.ReaderParameter;
import cn.ac.iscas.domain.component.transformer.TransformerParameter;
import cn.ac.iscas.domain.component.writer.DataSongWriterParameter;
import cn.ac.iscas.domain.component.writer.WriterParameter;
import cn.ac.iscas.service.common.analyzer.AnalyzerParameter;
import com.iscas.datasong.lib.annotation.table.DSStoreType;
import com.iscas.datasong.lib.annotation.table.DSTableName;
import com.iscas.datasong.lib.common.DataSongException;
import com.iscas.datasong.lib.common.Status;
import com.iscas.datasong.lib.common.StoreType;
import com.iscas.datasong.lib.util.DataSongExceptionUtils;
import com.iscas.datasong.lib.util.DataSongJsonUtils;


import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by ISCAS on 2017/9/27.
 */
@DSStoreType(StoreType.Sql)
@DSTableName("jobmetadata")
public class Job implements Serializable{
	//唯一标识
	protected String _id;

	//add 2020.03.02 任务的每次执行会产生一个内部Id
	protected String innerId;

	//用户自定义名称，可重复
	protected String name;

	//任务中涉及的组件数量
	//protected int componentCount;

	//已执行次数
	protected int executeCount;

	//最后一次执行时间
	protected Date  executeTime;

	//执行状态
	protected String status = JobStatus.WAITING.name();

	//执行耗时 ms
	protected long duration;

	protected String creator = "datasong";

	//创建时间
	protected Date createTime;

	//定时配置的cron表达式 add 2020.03.03
	protected String cron;

	//前置约束任务 add 2020.05.13
	protected String preJobId;

	//任务描述信息 add 2020.03.03
	protected String description;

	//任务内容  List<Component> content;
	protected Object content;

	//配置信息 Setting setting;
	//protected Object setting;

	//运行时信息，用于任务执行引擎自己内部使用
	protected String runInfo;
	protected String jobType;


	/**
	 * 修改content，将json串转成的map，转换成对应的对象
	 */
	public List<Component> getComponents() throws DataSongException {
		if(this.content != null){
			if( !(content instanceof List && ((List)content).size()>0 &&  ((List) content).get(0)instanceof Component)) {
				if(content instanceof  String){
					//如果有正则表达式，需要替换一下
					//content = ((String) content).replace("\\","\\\\");
					content = DataSongJsonUtils.fromJson((String) content, List.class);

				}

				List<Component> tmpContent = new ArrayList<>();
				List<Map<String, Object>> orignal = (List<Map<String, Object>>) this.content;
				for (Map map : orignal) {
					if (!map.containsKey("kind")) {
						throw new DataSongException(Status.PARAM_ERROR,
							String.format("name of component[%s] is null", map.get("_id")));
					}

//					try {
//						Component component = null;
//
//						ComponentType type = ComponentType.analyze((String) map.get("type"));
//
//						switch (type){
//							case reader:
//								component = DataSongJsonUtils.fromJson(DataSongJsonUtils.toJson(map), Component.class, ReaderParameter.class);
//								((ReaderParameter)component.getParameter()).setDatasongFileService(dataSongFileService);
//								break;
//							case transformer:
//								component = DataSongJsonUtils.fromJson(DataSongJsonUtils.toJson(map), Component.class, TransformerParameter.class);
//								break;
//							case analyzer:
//								component = DataSongJsonUtils.fromJson(DataSongJsonUtils.toJson(map), Component.class, AnalyzerParameter.class);
//								break;
//							case writer:
//								if( map.get("algorithm").equals("datasongwriter")){
//									component = DataSongJsonUtils.fromJson(DataSongJsonUtils.toJson(map), Component.class, DataSongWriterParameter.class);
//								}else {
//									component = DataSongJsonUtils.fromJson(DataSongJsonUtils.toJson(map), Component.class, WriterParameter.class);
//								}
//								break;
//						}
//
//						tmpContent.add(component);
//					} catch (Exception e) {
//						e.printStackTrace();
//						throw new DataSongException(Status.PARAM_ERROR, DataSongExceptionUtils.getExceptionInfo(e));
//					}
				}
				this.content = tmpContent;
			}
		}

		return (List<Component>) this.content;
	}

	public String get_id() {
		return _id;
	}

	public void set_id(String _id) {
		this._id = _id;
	}

	public String getInnerId() {
		return innerId;
	}

	public void setInnerId(String innerId) {
		this.innerId = innerId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getExecuteCount() {
		return executeCount;
	}

	public void setExecuteCount(int executeCount) {
		this.executeCount = executeCount;
	}

	public Date getExecuteTime() {
		return executeTime;
	}

	public void setExecuteTime(Date executeTime) {
		this.executeTime = executeTime;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}


	public String getCreator() {
		return creator;
	}

	public long getDuration() {
		return duration;
	}

	public void setDuration(long duration) {
		this.duration = duration;
	}

	public void setCreator(String creator) {
		this.creator = creator;
	}

	public Date getCreateTime() {
		return createTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}

	public String getCron() {
		return cron;
	}

	public void setCron(String cron) {
		this.cron = cron;
	}

	public String getPreJobId() {
		return preJobId;
	}

	public void setPreJobId(String preJobId) {
		this.preJobId = preJobId;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public Object getContent() {
		return content;
	}

	public void setContent(Object content) {
		this.content = content;
	}

	public String getRunInfo() {
		return runInfo;
	}

	public void setRunInfo(String runInfo) {
		this.runInfo = runInfo;
	}

	public List<Component>  buidObjJobContent(String dataSongFileService) throws DataSongException {
		if(this.content != null){
			if(!( content instanceof List && ((List)content).size()>0 &&  ((List) content).get(0)instanceof Component)) {
				if(content instanceof  String){
					content = ((String) content).replace("\\","\\\\");//如果有正则表达式，需要替换一下
					content = DataSongJsonUtils.fromJson((String) content, List.class);
				}

				List<Component> tmpContent = new ArrayList<>();
				List<Map<String, Object>> orignal = (List<Map<String, Object>>) this.content;
				for (Map map : orignal) {
					if (!map.containsKey("algorithm")) {
						throw new DataSongException(Status.PARAM_ERROR,
								String.format("name of component[%s] is null", map.get("_id")));
					}

					//反射动态解析组件参数
					/*try {
						Class clz = Class.forName((String) map.get("name"));

						Component component =
							DataSongJsonUtils.fromJson(DataSongJsonUtils.toJson(map), Component.class, clz);
						tmpContent.add(component);
					} catch (ClassNotFoundException e) {
						e.printStackTrace();
						throw new DataSongException(Status.PARAM_ERROR, DataSongExceptionUtils.getExceptionInfo(e));
					}*/
					try {
						Component component = null;

						ComponentType type = ComponentType.analyze((String) map.get("type"));

						switch (type){
							case reader:
								component = DataSongJsonUtils.fromJson(DataSongJsonUtils.toJson(map), Component.class, ReaderParameter.class);
								((ReaderParameter)component.getParameter()).setDatasongFileService(dataSongFileService);
								break;
							case transformer:
								component = DataSongJsonUtils.fromJson(DataSongJsonUtils.toJson(map), Component.class, TransformerParameter.class);
								break;
							case analyzer:
								component = DataSongJsonUtils.fromJson(DataSongJsonUtils.toJson(map), Component.class, AnalyzerParameter.class);
								break;
							case writer:
								if( map.get("algorithm").equals("datasongwriter")){
									component = DataSongJsonUtils.fromJson(DataSongJsonUtils.toJson(map), Component.class, DataSongWriterParameter.class);
								}else {
									component = DataSongJsonUtils.fromJson(DataSongJsonUtils.toJson(map), Component.class, WriterParameter.class);
								}
								break;
						}

						tmpContent.add(component);
					} catch (Exception e) {
						e.printStackTrace();
						throw new DataSongException(Status.PARAM_ERROR, DataSongExceptionUtils.getExceptionInfo(e));
					}
				}
				this.content = tmpContent;
			}
		}

		return (List<Component>) this.content;
	}

	public String getJobType() {
		return jobType;
	}

	public void setJobType(String jobType) {
		this.jobType = jobType;
	}
}

